#include "Matriz.h"

Matriz::Matriz(int filas, int columnas) {
    _nodoMatriz.filas = filas;
    _nodoMatriz.columnas = columnas;
    //_nodoMatriz.posicion = new int[filas * columnas];
    _nodoMatriz.posicion = (int*) mallocParametro(sizeof(int) * filas * columnas);

    _punteroADato = &_nodoMatriz;
}

Matriz::Matriz(void* punteroADato){
    this->_punteroADato = punteroADato;
}

Matriz::Matriz(string valor){

}

Matriz::~Matriz(){
    //delete[](_nodoMatriz.posicion);
    freeParametro(_nodoMatriz.posicion);
}

void* Matriz::damePunteroAMemoria() {
    return _nodoMatriz.posicion;
}

void Matriz::comparar(TipoDeDato& tipoDeDato,ostream& out) {
    NodoMatriz* otroValor = (NodoMatriz*) tipoDeDato.damePunteroADato();

    int otroFilas = (*otroValor).filas;
    int otroColumnas = (*otroValor).columnas;
    int* otroPosicion = (*otroValor).posicion;
    int esteFilas = _nodoMatriz.filas;
    int esteColumnas = _nodoMatriz.columnas;
    int* estePosicion = _nodoMatriz.posicion;

    int hastaFilas = min(otroFilas, esteFilas);
    int hastaColumnas = min(otroColumnas, esteColumnas);

    for( int i = 0; i < hastaFilas; i++ ){
        for( int j = 0; j < hastaColumnas; j++ ) {
            if ( estePosicion[i*esteColumnas+j] != otroPosicion[i*otroColumnas+j] ) {
                out << "Diferencia en la posicion [" << i << "," << j << "] de la matriz. Valor esperado: " << estePosicion[i*esteColumnas+j] << " .Valor obtenido: " << otroPosicion[i*otroColumnas+j] << endl;
            }
        }
    }

    int diferenciaFilas = abs(esteFilas - otroFilas);
    int diferenciaColumnas = abs(esteColumnas - otroColumnas);

    if ( diferenciaFilas != 0 ) {
        if (esteFilas > otroFilas) {
            out << "Existe una diferencia en la cantidad de filas. La salida esperada tiene mas filas que la obtenida. Detalle:" << endl;
            for ( int i = otroFilas; i < esteFilas; i++ ) {
                for ( int j = 0; j < esteColumnas; j++ ) {
                    out << "Posicion [" << i << "," << j << "] vale: " << estePosicion[i*esteColumnas+j] << endl;
                }
            }
        } else {
            out << "Existe una diferencia en la cantidad de filas. La salida obtenida tiene mas filas que la esperada. Detalle:" << endl;
            for ( int i = esteFilas; i < otroFilas; i++ ) {
                for ( int j = 0; j < otroColumnas; j++ ) {
                    out << "Posicion [" << i << "," << j << "] vale: " << otroPosicion[i*otroColumnas+j] << endl;
                }
            }
        }
    }

    if ( diferenciaColumnas != 0 ) {
        if (esteColumnas > otroColumnas) {
            out << "Existe una diferencia en la cantidad de columnas. La salida esperada tiene mas columnas que la obtenida. Detalle:" << endl;
            for ( int i = 0; i < esteFilas; i++ ) {
                for ( int j = otroColumnas; j < esteColumnas; j++ ) {
                    out << "Posicion [" << i << "," << j << "] vale: " << estePosicion[i*esteColumnas+j] << endl;
                }
            }
        } else {
            out << "Existe una diferencia en la cantidad de columnas. La salida obtenida tiene mas columnas que la esperada. Detalle:" << endl;
            for ( int i = 0; i < otroFilas; i++ ) {
                for ( int j = esteColumnas; j < otroColumnas; j++ ) {
                    out << "Posicion [" << i << "," << j << "] vale: " << otroPosicion[i*otroColumnas+j] << endl;
                }
            }
        }
    }
}

void Matriz::setearValor(int fila, int columna, int valor){
    _nodoMatriz.posicion[fila*_nodoMatriz.columnas + columna] = valor;
}

int Matriz::dameValor(int fila, int columna){
    return _nodoMatriz.posicion[fila*_nodoMatriz.columnas + columna];
}

ClaseDeDato Matriz::getClass() {
    return C_MATRIZ;
}
